#coding:utf-8

from mytree import MyTree
from enum import Enum
"""
行为树
2022年12月14日14:07:01

"""

class Result(Enum):
    Failed = 0         #  失败
    Ok = 1             # 成功
    Running = 2        # 运行中

class BH_Type(Enum):
    leaf        = 0    # 叶子节点
    sequence    = 1    # 顺序节点
    selector    = 2    # 选择节点
    decorator   = 3    # 装饰器
    circle      = 4    # 循环n次直到成功

class BHnode():
    def __init__(self):
        self.parent = 0
        self.child_list = []
        self.state = Result.Failed
        self.type = BH_Type.leaf
        self.action = None
    def showState(self):
        if self.state == Result.Failed:print('->失败')
        elif self.state == Result.Ok:print('->成功')
        elif self.state == Result.Running:print('->Running')
        else :print('未定义')
        return self.state

class BH_Tree(MyTree):
    def __init__(self,item:BHnode = None) -> None:
        super().__init__(item)

    def __append_leaf(self,leaf):
        """
        往boot节点下添加叶子
        返回挂载这个叶子的地址
        """
        if self.node is None:
            self.node = leaf
            return self
        item = BH_Tree(leaf)
        if self.lchild is not None:
            pnode = self.lchild
            while pnode.rchild is not None:
                pnode = pnode.rchild
            pnode.rchild = item
        else:
            self.lchild = item
        return item

    def append_leaf(self,leaf:BHnode):
        leaf.parent = self
        bh = self.__append_leaf(leaf)
        self.node.child_list.append(bh) # self.node的类型一定是BHnode
        return bh
    
    def append_branch(self,branch:MyTree):
        branch.node.parent = self
        self.tree_append_branch(branch)
        self.node.child_list.append(branch)

    def __bh_action(self,item):
        if item is None:return
        self.__bh_action(item.lchild)
        node = item.node
        parentTree = node.parent
        parentNode = parentTree.node
        parentNode.state = node.action()
        node.state = parentNode.state
        if node.type == BH_Type.leaf :
            if parentNode.type == BH_Type.sequence and parentNode.state == Result.Failed :return
            if parentNode.type == BH_Type.selector and parentNode.state == Result.Ok :return 

        elif node.type == BH_Type.sequence :           
            if parentNode.type == BH_Type.sequence and parentNode.state == Result.Failed :return # 如果父节点是顺序结构，只要有一个结果为假，就返回
            if parentNode.type == BH_Type.selector and parentNode.state == Result.Ok :return # 如果父节点是选择结构，只要有一个结果为真，就返回

        elif node.type == BH_Type.selector :
            if parentNode.type == BH_Type.sequence and parentNode.state == Result.Failed:return
            if parentNode.type == BH_Type.selector and parentNode.state == Result.Ok:return

        elif node.type == BH_Type.decorator :  
            if parentNode.type == BH_Type.sequence and parentNode.state == Result.Failed:return
            if parentNode.type == BH_Type.selector and parentNode.state == Result.Ok:return          

        elif node.type == BH_Type.circle :
            if parentNode.type == BH_Type.sequence and parentNode.state == Result.Failed:return
            if parentNode.type == BH_Type.selector and parentNode.state == Result.Ok:return

        self.__bh_action(item.rchild)

    def bh_action(self):
        self.__bh_action(self)

    class Sequence(BHnode):
        """顺序节点"""
        def __init__(self,action = None) -> None:
            super().__init__()
            self.type = BH_Type.sequence
            if action is not None:
                self.action = action
            else:
                self.action = self.default_action
        def default_action(self):
            print("顺序节点结果：")
            self.showState()
            return self.state

    class Leaf(BHnode):
        """叶子节点（动作节点）"""
        def __init__(self,action = None):
            super().__init__()
            self.type = BH_Type.leaf
            if action is not None:
                self.action = action
            else:
                self.action = self.default_action
        
        def default_action(self):
            print('leaf action Ok')      
            return Result.Ok 

    class Select(BHnode):
        """选择节点"""
        def __init__(self,action = None):
            super().__init__()
            self.type = BH_Type.selector
            if action is not None:
                self.action = action
            else:
                self.action = self.default_action

        def default_action(self):
            print("选择节点结果：")
            self.showState()
            return self.state              

    class Decorator(BHnode):
        """装饰器节点"""
        def __init__(self,action = None):
            super().__init__()
            self.type = BH_Type.decorator
            if action is not None:
                self.action = action
            else:
                self.action = self.always_failed

        def always_failed(self):
            """装饰器：总是失败"""
            return Result.Failed

        def always_ok(self):
            """装饰器：总是成功"""
            return Result.Ok
        
        def inverter(self):
            """装饰器：反向器"""
            if self.state == Result.Failed :return Result.Ok
            else :Result.Failed

    class Circle(BHnode):
        """循环N次，直到成功"""
        def __init__(self,times = 0):
            super().__init__()
            self.type = BH_Type.circle
            self.action = self.circle_action        
            self.times = times

        def circle_action(self):
            times = self.times - 1  # 默认执行一次，所以要减一
            boot = self.child_list[0]
            
            while boot.node.state == Result.Failed and times:
                print('times = %d'%(times))
                BH_Tree.bh_action(boot)
                times -= 1
                print('重复执行节点:{0}'.format(boot.node.state))
            return self.state

 
def WalktoDoor():
    print("Walk to Door")
    return Result.Ok

def OpenDoor():
    print("Open Door")
    return Result.Failed

def WalkThroughDoor():
    print("Walk through Door")
    return Result.Ok

def CloseDoor():
    print("Close the Door")
    return Result.Ok

def UnlockDoor():
    print("开锁")
    return Result.Ok

counter = 0
def SmashDoor():
    global counter
    counter +=1
    print("打碎门")
    if(counter >3):
        return Result.Ok
    return Result.Failed



if __name__ == "__main__":
    boot = BH_Tree()
    sequence1 = boot.append_leaf(boot.Sequence())
    sequence1.append_leaf(boot.Leaf(WalktoDoor))
    select1 = sequence1.append_leaf(boot.Select())
    sequence1.append_leaf(boot.Leaf(WalkThroughDoor))
    sequence1.append_leaf(boot.Leaf(CloseDoor))
    select1.append_leaf(boot.Leaf(OpenDoor))
    sequence2 = select1.append_leaf(boot.Sequence())
    circle1 = select1.append_leaf(boot.Circle(4))
    sequence3 = circle1.append_leaf(boot.Sequence())
    sequence3.append_leaf(boot.Leaf(WalktoDoor))
    sequence3.append_leaf(boot.Leaf(SmashDoor))
    sequence2.append_leaf(boot.Leaf(UnlockDoor))
    sequence2.append_leaf(boot.Leaf(OpenDoor))
    boot.bh_action()


